package com.handpay.framework.swiper;

import java.util.concurrent.TimeoutException;

import com.handpay.zztong.hp.log.HPLog;

/**
 * Created by jmshuai on 2014/8/12.
 */
class AsynSwiperLock {
    private volatile boolean notifyWait = false;
    public static final int IDLE = -1;
    private Object objLockBT = new Object();
    //TODO CommandType暂时使用int型。以后采用Enum
    private volatile int mCurrentCommandType = IDLE;
    public static final int GETCSN = IDLE + 2;
    public static final int AFFIRM_AMOUNT = IDLE + 3;
    public static final int NEW_SWIPE_CARD = IDLE + 4;
    public static final int NEW_INPUT_PWD = IDLE + 5;
    public static final int BIND_CARD = IDLE + 6;
    public static final int CACL_MAC = IDLE + 7;
    public static final int CACL_DATA = IDLE + 8;
    public static final int OLD_SWIPE_CARD = IDLE + 9;
    public static final int OLD_INPUT_PWD = IDLE + 10;
    public static final int CONNECT = IDLE + 11;
    /**
     * 锁住当前进程timeout时间
     * @param timeout 以s为单位, -1 表示没有超时时间
     * @throws java.util.concurrent.TimeoutException
     */
    public void lock(long timeout, int commandType) throws TimeoutException {
        synchronized (objLockBT) {
            try {
                notifyWait = false;
                mCurrentCommandType = commandType;
                HPLog.i("lock", "lock at commandType:" + commandTypeToString(mCurrentCommandType));
                //wait要有超时机制，否则调用lock的线程会死等。造成线程不再可用
                if (timeout > 0) {
                    objLockBT.wait(timeout * 1000);
                } else {
                    objLockBT.wait();
                }
                HPLog.i("lock", "unlock at commandType:" + commandTypeToString(mCurrentCommandType));
                mCurrentCommandType = IDLE;
                if (!notifyWait) {
                    //TODO: Spurious wakeup也会导致出现timeoutException
                    throw new TimeoutException();
                }
            } catch (InterruptedException e) {
                HPLog.e("lock","should never enter!",e);
            }
        }
    }
    public String commandTypeToString(int commandType) {
        String cmdDes = "IDLE";
        switch (commandType) {
            case 0: {
                cmdDes = "cmdType0";
                break;
            }
            case 1: {
                cmdDes = "getCsn";
                break;
            }
            case 2: {
                cmdDes = "affirmAmount";
                break;
            }
            case 3: {
                cmdDes = "newSwipeCard";
                break;
            }
            case 4: {
                cmdDes = "newInputPwd";
                break;
            }
            case 5: {
                cmdDes = "bindCard";
                break;
            }
            case 6: {
                cmdDes = "CALCMAC";
                break;
            }
            case 7: {
                cmdDes = "CALCDATA";
                break;
            }
            case 8: {
                cmdDes = "oldSwipeCard";
                break;
            }
            case 9: {
                cmdDes = "oldInputPwd";
                break;
            }
            case 10: {
                cmdDes = "connect";
                break;
            }
        }
        return cmdDes;
    }

    /**
     * 尝试解锁。returnCmd == IDLE时，不管当前锁在哪个命令，都解锁。
     * @param returnCmd
     */
    public void unlock(int returnCmd) {
        synchronized (objLockBT) {
            //只有当前指令收到返回结果的时候，才notify
            if (returnCmd == IDLE || (returnCmd == mCurrentCommandType && mCurrentCommandType != IDLE)) {
                HPLog.i("unlock", "notify at commandType:" + commandTypeToString(returnCmd)
                        + " and currentCmd " + commandTypeToString(mCurrentCommandType));
                notifyWait = true;
                objLockBT.notifyAll();
            } else {
                HPLog.i("unlock", "fail to notify at commandType:" + commandTypeToString(returnCmd));
            }
        }
    }
    public int getCurrrentCmdType() {
        return mCurrentCommandType;
    }
}
